#include "Rect.h" 
#include <fstream>

//����������� � ����������� ��� ������������� ���������� ������
Rect::Rect(int top, int left, int bottom, int right, colour col)
	:Shape(col), m_top_left(top, left), m_bottom_right(bottom, right)
{	
	Standarting();
}
Rect::Rect(Point& top_left, Point& bottom_right, colour col)
{
}
//����� "������������" ��������������
void Rect::Standarting()
{	
	double m_top, m_left, m_bottom, m_right;
	m_top_left.GetAll(m_top, m_left);
	m_bottom_right.GetAll(m_bottom, m_right);

	if (m_right < m_left)
	{
		int tmp = m_right;
		m_right = m_left;
		m_left = tmp;
	}
	
	if (m_bottom < m_top)
	{
		int tmp = m_bottom;
		m_bottom = m_top;
		m_top = tmp;
	}		
}

//����������� �����������
Rect::Rect(const Rect& other):Shape(other),m_top_left(other.m_top_left), m_bottom_right(other.m_bottom_right) {}

//����� ������� ����������� ���������� ������ ������������ ��������
void Rect::SetAll(int left, int right, int top, int bottom) 
{
	m_top_left.Set_All(top, left);
	m_bottom_right.Set_All(bottom, right);
	
	Standarting();
}

//����� ������� "�������" �������� private-���������� ������.
void Rect::GetAll(int& left, int& right, int& top, int& bottom) const
{
	double m_top, m_left, m_bottom, m_right;
	m_top_left.GetAll(m_top, m_left);
	m_bottom_right.GetAll(m_bottom, m_right);

	left = m_left;
	right = m_right;
	top = m_top;
	bottom = m_bottom;
}

Rect::~Rect()
{
	
}

Shape* Rect::CopyObj() const
{
	return new Rect(*this); 
}

double Rect::Get_area() const
{
	double m_top, m_left, m_bottom, m_right;
	m_top_left.GetAll(m_top, m_left);
	m_bottom_right.GetAll(m_bottom, m_right);
	return static_cast<double>((m_right - m_left) * (m_bottom - m_top));
}

const Point& Rect::Get_center() const
{
	double m_top, m_left, m_bottom, m_right;
	m_top_left.GetAll(m_top, m_left);
	m_bottom_right.GetAll(m_bottom, m_right);
		
	return Point((m_right + m_left) / 2, (m_bottom + m_top) / 2);
}

double Rect::Get_distance() const
{
	double x, y;
	Get_center().GetAll(x, y);
	double dis = abs(x * x) + abs(y * y);

	return sqrt(dis);
}

Shape& Rect::operator=(const Shape& other)
{
	//if (dynamic_cast<Rect*>(const_cast<Shape*>(&other)))
	//{
	//	*this = static_cast<const Rect&>(other);
	//	return *this;
	//}
	////else throw "Err another type (not Rect)";
	//else throw &other;
	return *this = dynamic_cast<const Rect&>(other);
}

bool Rect::operator==(const Shape& other) const
{
	const Rect* p = dynamic_cast<Rect*>(const_cast<Shape*>(&other));
	if (p) {
		//return Shape::operator==(*p) && m_top_left == p->m_top_left && m_bottom_right == p->m_bottom_right;//���� �� ���������� �������� ���������
		return *this == *p;
	}
	return false;	
}

bool Rect::operator==(const Rect& other) const
{
	if (m_colour != other.m_colour) { return false; }
	
	if (m_top_left == other.m_top_left && m_bottom_right == other.m_bottom_right) { return true; }

	return false;
}

std::ostream& operator<<(std::ostream& os, const Rect& rect)
{
	double m_top, m_left, m_bottom, m_right;
	rect.m_top_left.GetAll(m_top, m_left);
	rect.m_bottom_right.GetAll(m_bottom, m_right);

	os<<static_cast<const Shape&>(rect);
	os << "distance: " << rect.Get_distance() << " ";
	os << "area: " << rect.Get_area() << " ";
	os << " m_top: " << m_top <<" m_left: " << m_left << " m_bottom: " << m_bottom << " m_right: "<< m_right;
	return os;	
}

Rect& operator>>(std::ifstream& is, Rect& rect)
{
	char  buff[20]; 
	size_t m_colour;
	static colour arr[]{ RED, GREEN, BLUE, BLACK };
	is >> buff >> m_colour;
	rect.m_colour = arr[m_colour];
	is >> buff >> buff >> buff >> buff;
	is >> rect.m_top_left;
	is >> rect.m_bottom_right;

	return rect;	
}
